﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using DreamStore.WebShop.Extensibility;
using DreamStore.WebShop.Models;
using DreamStore.WebShop.Services;
using DreamStore.WebShop.ViewModels;
using Orchard;
using Orchard.ContentManagement;
using Orchard.Core.Title.Models;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Mvc;
using Orchard.Security;
using Orchard.Themes;

namespace DreamStore.WebShop.Controllers
{
    
    public class OrderController : Controller
    {
        private readonly dynamic _shapeFactory;
        private readonly IOrderService _orderService;
        private readonly IAuthenticationService _authenticationService;
        private readonly IShoppingCart _shoppingCart;
        private readonly ICustomerService _customerService;
        private readonly Localizer _t;
        private readonly IPaymentServiceProvider _paymentServiceProviders;
        private readonly IEmailSenderServiceProvider _emailSenderServiceProviders;

        public OrderController(IShapeFactory shapeFactory, IOrderService orderService, IAuthenticationService authenticationService, IShoppingCart shoppingCart, ICustomerService customerService, IPaymentServiceProvider paymentServiceProviders, IEmailSenderServiceProvider emailSenderServiceProviders)
        {
            _shapeFactory = shapeFactory;
            _orderService = orderService;
            _authenticationService = authenticationService;
            _shoppingCart = shoppingCart;
            _customerService = customerService;
            _t = NullLocalizer.Instance;
            _paymentServiceProviders = paymentServiceProviders;
            _emailSenderServiceProviders = emailSenderServiceProviders;
        }

        [Themed,HttpPost]
        public ActionResult Create()
        {
            var user = _authenticationService.GetAuthenticatedUser();
            if (user == null)
            {
                throw new OrchardSecurityException(_t("Login required"));
            }

            var customer = user.ContentItem.As<CustomerPart>();
            if (customer == null)
            {
                throw new InvalidOperationException(_t("The currently logged in user is not a customer").ToString());
            }

            var order = _orderService.CreateOrder(customer.Id, _shoppingCart.Items);

            var paymentRequest = new PaymentRequest(order);

            _paymentServiceProviders.RequestPayment(paymentRequest);    

            dynamic shape;

            if (paymentRequest.PaymentServiceProviderViewModels.Any())
            {
                shape = _shapeFactory.Order_SelectPaymentServiceProvider(
                    Providers: paymentRequest.PaymentServiceProviderViewModels);
            }
            else
            {
                // If we got here, no PSP handled the OrderCreated event, so we'll just display the order.
                shape = _shapeFactory.Order_Created(
                    Order: order,
                    Products: _orderService.GetProducts(order.Details).ToArray(),
                    Customer: customer,
                    InvoiceAddress: (dynamic)_customerService.GetAddress(user.Id, "InvoiceAddress"),
                    ShippingAddress: (dynamic)_customerService.GetAddress(user.Id, "ShippingAddress")
                    );
                _shoppingCart.RemoveCart();
            }
          
            return new ShapeResult(this, shape);

        }

        [Themed]
        public ActionResult PaymentResponse()
        {
            var args = new PaymentResponse(HttpContext);

            _paymentServiceProviders.ProcessResponse(args);

            if (!args.WillHandleResponse)
                throw new OrchardException(_t("Such things mean trouble"));

            var order = _orderService.GetOrderByNumber(args.OrderReference);
            _orderService.UpdateOrderStatus(order, args);

            if (order.Status == OrderStatus.Paid)
            {
                var customer = _customerService.GetCustomer(order.CustomerId);
                var user = customer.User;

                var orderLines = (from detailRecord in order.Details
                                  let product = _orderService.GetProduct(detailRecord.ProductId)
                                  let title = product.As<TitlePart>().Title
                                  select new OrderLine
                                         {
                                             ProductName = title, Quantity = detailRecord.Quantity, UnitPrice = detailRecord.UnitPrice, TotalPrice = detailRecord.SubTotal
                                         });

                // Send some notification mail message to the customer that the order was paid.
                _emailSenderServiceProviders.SendOrderConfirmationMail(order, orderLines, user, customer);
        

                //TODO : We may also initiate the shipping process from here
            }
            _shoppingCart.RemoveCart();
            return new ShapeResult(this, _shapeFactory.Order_PaymentResponse(Order: order, PaymentResponse: args));
        }
    }
}
